 
import { PositionHelper } from "utils/position/PositionHelper";
import { FormationPattern } from "./FormationPattern";
import {   Matrix3, SlotAssignment, Static } from "./types";
import { Math2D } from "algorithm/Math2d";


export class FormationManager<T extends Charactor=Charactor,U extends FormationPattern<T>=FormationPattern<T>>
{

    private team:ITeam;
    private slotAssignments:SlotAssignment<T>[]=[];

    private driftoffset!:Static;

    private pattern!:U;
    constructor(team:ITeam,pattern:U)
    {
        this.team = team;
        this.pattern = pattern;
        this.initSlotAssignments(pattern);
    }
    // 初始化槽位
    private initSlotAssignments(pattern:U)
    {
        for(let idx=0;idx<pattern.getSlotCount();idx++)
        {
            const slot: SlotAssignment<T> ={charactor:null as any,slotNumber:idx};
       
            this.slotAssignments.push(slot);
        }
    }
    // 更新槽位角色的分配,这里是初始化的时候，设置的数据
    public updateSlotAssignments()
    {
        // 简单的顺序分配
        for(let idx=0;idx<this.slotAssignments.length;idx++)
        {
            this.slotAssignments[idx].slotNumber = idx;
        }

        this.driftoffset = this.pattern.getDriftOffset(this.slotAssignments);
    }

    /**
     * 更新slot 的爬。
     */
    public update()
    {
        // 当减员时
        const expireslot = this.slotAssignments.find(e=>!Game.creeps[ e.charactor.name]);
        if(expireslot)
        {
            const existCreeps = this.slotAssignments.filter(e=>!Game.creeps[ e.charactor.name]);
            for(const e of this.slotAssignments)
            {
                e.charactor = null as any;
            }
            for(const c of existCreeps)
            {
                this.addCharactor(c.charactor);
            }
        }
    }

    // 添加新的角色,如果没有更多可用的槽位返回false
    public addCharactor(charactor:T)
    {
        for(const e of this.slotAssignments)
        {
            if(!e.charactor && this.pattern.getSlotCost({charactor:charactor,slotNumber:e.slotNumber})>0)
            {
                e.charactor = charactor;
                return true;
            }
        }
        return false;
    }
    public getSlots()
    {
        return this.pattern.getSlotLocations();
    }
 
    public getAssignments()
    {
        return this.slotAssignments
    }
    // 移除槽位上的角色
    public removeCharactor(charactor:T)
    {
        for(const e of this.slotAssignments)
        {
            if(e.charactor.name == charactor.name)
            {
                e.charactor = undefined as any;
                
            }
        }
    }

    // 发送每个角色的新槽位位置
    public updateSlots()
    {
        // const anchor = this.getAnchorPoint();
        // const orientatuibMatrix:Matrix3=anchor.orientation;

    }


    // 移动
    public move(offset:IFVector2):IFVector2[]
    {
        const anchor = this.getTransform();
        //anchor.transform.translate(offset.x,offset.y);
        anchor.transform.multplay(new Matrix3().makeTranslate(offset));
        return this.getSlotLocations(anchor.transform)
    }
   // 移动
    public moveTo(target:IFVector2):IFVector2[]
    {
        const anchor = this.team.getAnchor();
        const offset ={x: target.x-anchor.x,y:target.y-anchor.y};
        return this.move(offset);
    }
    // 旋转
    public rotate(radian:number):IFVector2[]
    {
        const anchor = this.getTransform(radian);
        // anchor.transform.rotate(radian);
        const poss =  this.getSlotLocations(anchor.transform);
        const indexes = this.pattern.getRotateIndex();
        if(indexes)
        {
            for(let i=0;i<poss.length;i++)
            {
                if(!indexes.includes(i))
                {
                    const pos = Game.creeps[this.slotAssignments[i].charactor.name]?.pos;
                    if(pos)
                    {
                        poss[i].x = pos.x
                        poss[i].y = pos.y
                    }
                    
                }
            }
        }
        return poss;
    }

    private getSlotLocations(worldtransform:Matrix3)
    {
        const pos:IFVector2[]=[];
        for(let i=0;i<this.slotAssignments.length;i++)
        {
            const relativepos = this.pattern.getSlotLocation(i);
            const newpos = worldtransform.TransltePoint(relativepos);
            pos.push({x:newpos.x,y:newpos.y});
        }
        return pos;
    }

    private getTransform(deltaAngle:number=0)
    {
        // 查找锚点位置,世界坐标，世界朝向
       
        const dir = this.team.getDirection();
        const origin = this.getCenter(this.team.getAnchor(), Math2D.multiply(dir,-1));
        const mat = new Matrix3().makeTranslate(Math2D.subtract(origin, this.pattern.getOffset()));
        const angle =   Math2D.radian(dir,this.pattern.getDirection());
        let addAngle = deltaAngle+angle;
        const mat2 = mat.clone().rotateWith(this.pattern.getOffset(),-(addAngle>Math.PI*2?addAngle-Math.PI*2:addAngle));
        // global.Log.Info(`${angle}:${deltaAngle} 旋转角度为${addAngle} 真实旋转:${addAngle>Math.PI*2?addAngle-Math.PI*2:addAngle}`);
        //return  new Static(new Matrix3().rotateWith(origin,addAngle))
        return new Static(mat2.multplay(mat));
    }

    private getCenter(anchor:IFVector2,dir_y:IFVector2)
    {
        const dirx = {x:dir_y.y,y:-dir_y.x};
        const rltv_offset = this.pattern.getOffset();
        const offy = Math2D.multiply(dir_y,rltv_offset.y);
        const offx = Math2D.multiply(dirx,rltv_offset.x);
        const abs_offset =  Math2D.add(offy,offx);
        return  Math2D.add(anchor,abs_offset)
    }
    public Center()
    {
        const dir = this.team.getDirection();
        return this.getCenter(this.team.getAnchor(), Math2D.multiply(dir,-1));
    }
}
